package com.plugins.utils;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;

/**
 * 注解扫描
 */
public class ClassUtil {
    /**
     * 扫描获得所有标注注解clazz的java Class
     *
     * @param context         context
     * @param annotationClass 注解class
     * @param applicationId   applicationId
     * @param packageNameList 需要扫描的package
     * @return
     */
    public static List<Class> scanAllClass(Context context, Class annotationClass, String applicationId, String... packageNameList) {
        List<Class> classList = new ArrayList<>();
        try {
            ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(applicationId, 0);
            String apkName = applicationInfo.sourceDir;
            DexFile dexFile = new DexFile(apkName);
            PathClassLoader classLoader = new PathClassLoader(apkName, Thread.currentThread().getContextClassLoader());
            Enumeration<String> entries = dexFile.entries();
            while (entries.hasMoreElements()) {
                String entry = entries.nextElement();
                if (isNeedClass(entry, packageNameList)) {
                    Class<?> entryClass = classLoader.loadClass(entry);
                    if (entryClass != null) {
                        Annotation[] annotations = entryClass.getAnnotations();
                        for (Annotation annotation : annotations) {
                            if (annotation.annotationType().equals(annotationClass)) {
                                classList.add(entryClass);
                            }
                        }
                    }
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return classList;
    }

    private static boolean isNeedClass(String entry, String... packageNameList) {
        for (String packageName : packageNameList) {
            if (entry.startsWith(packageName)) {
                return true;
            }
        }
        return false;
    }
}
